#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdint.h> 
#include <sys/stat.h> 

int main(int argc, char* argv[]) 
{
    if (argc != 2) 
    {
        perror("argc err");
        return -1;
    }
    char *save_dir = argv[1];
    int listen_server = socket(AF_INET, SOCK_DGRAM, 0); // 服务端监听socket
    if(listen_server < -1) 
    {
        perror("socket err");
        return -1;
    }
    printf("socket OK!\n");
    struct sockaddr_in addr = 
    {
        .sin_family = AF_INET,
        .sin_port = htons(8888),
        .sin_addr.s_addr = INADDR_ANY
    };

    if(bind(listen_server, (struct sockaddr*)&addr, sizeof(addr)) == -1) 
    {
        perror("bind err");
        close(listen_server);
        return -1;
    };
    printf("bind OK!\n");
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr); 
    memset(&client_addr, 0, sizeof(client_addr));
    char send_buf[32] = "This is server!";
    char recv_buf[32] = {0};
    if(recvfrom(listen_server, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&client_addr, &client_addr_len) < 0)
    {
    	perror("recvfrom err");
        close(listen_server);
        return -1;
    }
    printf("recv from client:%s\n", recv_buf);
    if(sendto(listen_server, send_buf, sizeof(send_buf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr)) < 0)
    {
    	perror("sendto err");
        close(listen_server);
        return -1;
    }
    printf("send to client:%s\n", send_buf);
    
    for(int i = 0; i < 2; i++)
    {
        char filename[100] = {0};	
        recvfrom(listen_server, filename, sizeof(filename), 0, (struct sockaddr*)&client_addr, &client_addr_len);
        printf("\n%s recv.....\n", filename);
        
        // 接收文件大小
        uint64_t file_size;
        recvfrom(listen_server, &file_size, sizeof(file_size), 0, (struct sockaddr*)&client_addr, &client_addr_len);
        file_size = be64toh(file_size); // 转换字节序
        
        printf("File size: %lu bytes\n", file_size);
        
        char filepath[200] = {0};
        snprintf(filepath, sizeof(filepath), "%s%s", save_dir, filename);
        printf("Receiving file: %s\n", filepath);     
        FILE *file = fopen(filepath, "wb");
        if(!file)
        {
            perror("fopen error");
            close(listen_server);
            fclose(file);
            return -1;	
        }
        char recvbuff[1024];
        uint64_t recvlen;
        uint64_t total_received = 0;
        while(total_received < file_size)
        {
            recvlen = recvfrom(listen_server, recvbuff, sizeof(recvbuff), 0, (struct sockaddr*)&client_addr, &client_addr_len); 
            total_received += recvlen;
            if(recvlen <= 0)
            {
                perror("recvfrom error");
                fclose(file);
                close(listen_server);
                return -1;
            }

        fwrite(recvbuff, 1, recvlen, file);

        }
        fclose(file);
        printf("%s recv success!\n", filename);
    }

    close(listen_server);
    return 0;
}
